package com.handpay.framework.swiper;

import android.content.Context;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;

import com.handpay.framework.swiper.ic.IShowSelectApplication;
import com.handpay.framework.utils.CommonUtils;
import com.handpay.zztong.hp.R;
import com.handpay.zztong.hp.config.ZZTConfig;
import com.handpay.zztong.hp.log.HPLog;
import com.newland.me.ConnUtils;
import com.newland.me.DeviceManager;
import com.newland.mtype.BatteryInfoResult;
import com.newland.mtype.ConnectionCloseEvent;
import com.newland.mtype.Device;
import com.newland.mtype.DeviceInfo;
import com.newland.mtype.DeviceOutofLineException;
import com.newland.mtype.DeviceRTException;
import com.newland.mtype.DeviceType;
import com.newland.mtype.ModuleType;
import com.newland.mtype.ProcessTimeoutException;
import com.newland.mtype.common.ExCode;
import com.newland.mtype.common.MESeriesConst;
import com.newland.mtype.common.MESeriesConst.TrackEncryptAlgorithm;
import com.newland.mtype.conn.DeviceConnParams;
import com.newland.mtype.event.AbstractProcessDeviceEvent;
import com.newland.mtype.event.DeviceEvent;
import com.newland.mtype.event.DeviceEventListener;
import com.newland.mtype.module.common.cardreader.CardReader;
import com.newland.mtype.module.common.cardreader.OpenCardReaderEvent;
import com.newland.mtype.module.common.emv.EmvControllerListener;
import com.newland.mtype.module.common.emv.EmvModule;
import com.newland.mtype.module.common.emv.EmvTransController;
import com.newland.mtype.module.common.emv.EmvTransInfo;
import com.newland.mtype.module.common.lcd.LCD;
import com.newland.mtype.module.common.pin.AccountInputType;
import com.newland.mtype.module.common.pin.EncryptType;
import com.newland.mtype.module.common.pin.MacAlgorithm;
import com.newland.mtype.module.common.pin.PinInput;
import com.newland.mtype.module.common.pin.PinInputEvent;
import com.newland.mtype.module.common.pin.PinInputResult;
import com.newland.mtype.module.common.pin.PinManageType;
import com.newland.mtype.module.common.pin.WorkingKey;
import com.newland.mtype.module.common.swiper.SwipResult;
import com.newland.mtype.module.common.swiper.SwipResultType;
import com.newland.mtype.module.common.swiper.Swiper;
import com.newland.mtype.module.common.swiper.SwiperReadModel;
import com.newland.mtype.module.common.swiper.TrackSecurityPaddingType;
import com.newland.mtype.util.ISOUtils;
import com.newland.mtypex.bluetooth.BlueToothV100ConnParams;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;
import java.util.Locale;
import java.util.Random;
import java.util.concurrent.TimeUnit;


/**
 * 新大陆ME15蓝牙刷卡器
 *
 * @author yliang
 */
public class NewlandSwiperME15 implements IPersonalSwiper {
    private static final String TAG = "NewlandSwiperME15";
    private static final String BANK_ACCOUNT_HASH_KEY = "account_hash";
    private DeviceManager mDeviceManager;
    private static final String ME15_DRIVER_NAME = "com.newland.me.ME3xDriver";
    private volatile boolean mIsSwiperOK = true;
    private DeviceConnParams mConnParams;
    private Hashtable<String, String> mHTData = new Hashtable<String, String>();
    // 用于获取字符串
    private Context mContext;
    protected IShowSelectApplication mSelectApplication;

    /**
     * 初始化设备
     *
     * @param context
     * @param params
     */
    private void initMe3xDeviceController(Context context,
                                          DeviceConnParams params) {
        mConnParams = params;
        mContext = context;
        mDeviceManager.init(context, ME15_DRIVER_NAME, params,
                new DeviceEventListener<ConnectionCloseEvent>() {
                    @Override
                    public void onEvent(ConnectionCloseEvent event,
                                        Handler handler) {
                        if (event.isSuccess()) {
                            // appendInteractiveInfoAndShow("设备被客户主动断开！");
                            HPLog.e(TAG, "〈〈〈〈〈DeviceEventListener〉〉〉〉〉Exception--event.isSuccess()");
                            mIsSwiperOK = false;
                        }
                        if (event.isFailed()) {
                            // appendInteractiveInfoAndShow("设备链接异常断开！" +
                            // event.getException().getMessage());
                            HPLog.e(TAG, "〈〈〈〈〈DeviceEventListener〉〉〉〉〉Exception--event.isFailed()");
                            mIsSwiperOK = false;
                        }
                    }

                    @Override
                    public Handler getUIHandler() {
                        return null;
                    }
                });
        // appendInteractiveInfoAndShow("驱动版本号："+controller.getCurrentDriverVersion());

    }

    /**
     * 尝试连接刷卡器。请在每个刷卡器操作之前执行此操作。
     *
     * @return true表示连接成功，否则连接失败
     */
    public boolean connect() {
        try {
            //刷卡器连接前做延时操作,避免极个别手机在设备不存在蓝牙配对列表中时出错。
            Thread.sleep(300);

            mDeviceManager.connect();
            mDeviceManager.getDevice().setBundle(mConnParams);
        } catch (Exception e) {
            HPLog.i(TAG, "", e);
            HPLog.e(TAG, "〈〈〈〈〈connect〉〉〉〉〉Exception");
            mIsSwiperOK = false;
        }
        return mIsSwiperOK;
    }

    /**
     * 加密之前，先格式化数据。
     *
     * @param data
     * @param cover
     * @return
     */
    public static byte[] formatEncData(byte[] data, int cover) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            bos.write(data);
        } catch (IOException e) {
            return null;
        }
        if (bos.size() % 8 != 0) {
            bos.write(0x00);
            while (bos.size() % 8 != 0) {
                bos.write(cover);
            }
        }
        return bos.toByteArray();
    }

    private String encData(String data, String factor) {
        String str = null;
        if (!connect()) {
            return str;
        }
        try {
            HPLog.i(TAG, "encData: before:" + data);
            WorkingKey localWorkingKey = new WorkingKey(
                    MKIndexConst.DEFAULT_MUTUALAUTH_WK_INDEX,
                    CommonUtils.hexStringToBytes(factor));
            byte[] array = formatEncData(CommonUtils.hexStringToBytes(data),
                    0x00);
            HPLog.i(TAG,
                    "encData: before:" + CommonUtils.bytesToHexString(array));
            PinInput pinInput = (PinInput) mDeviceManager.getDevice()
                    .getStandardModule(ModuleType.COMMON_PININPUT);

//			str = CommonUtils.bytesToHexString(pinInput
//					.encrypt(localWorkingKey, EncryptType.DISPERSE_ECB, array,
//							new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//									0x00, 0x00 }));

            // use demo for test.
            str = CommonUtils.bytesToHexString(pinInput
                    .encrypt(localWorkingKey, EncryptType.DISPERSE_ECB, array,
                            new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                    0x00, 0x00}));

            HPLog.i(TAG, "encData: after:" + str);
            return str.toUpperCase(Locale.US);
        } catch (Exception localException) {
            HPLog.e(TAG, "encData", localException);
        }
        return str;
    }

    private String encMac(byte[] data, String factor) {
        String str = null;
        if (!connect()) {
            return str;
        }
        try {
            PinInput pinInput = (PinInput) mDeviceManager.getDevice()
                    .getStandardModule(ModuleType.COMMON_PININPUT);
            byte[] arrayOfByte = pinInput.calcMac(
                    MacAlgorithm.DISPERSE_MAC_X99, PinManageType.FIXED,
                    new WorkingKey(MKIndexConst.DEFAULT_MAC_WK_INDEX,
                            CommonUtils.hexStringToBytes(factor)), data);
            byte[] retBuf = new byte[4];
            System.arraycopy(arrayOfByte, 0, retBuf, 0, 4);
            str = CommonUtils.bytesToHexString(retBuf);
            return str.toUpperCase(Locale.US);
        } catch (Exception e) {
            HPLog.e(TAG, "calc mac failed", e);
        }
        return str;
    }

    private String encPin(byte[] data, String factor) {
        String str = null;
        if (!connect()) {
            return str;
        }
        try {
            PinInput pinInput = (PinInput) mDeviceManager.getDevice().getStandardModule(ModuleType.COMMON_PININPUT);

            PinInputResult pinInputResult = pinInput.startPinInputWithoutKeyboard(new WorkingKey(MKIndexConst.DEFAULT_PIN_WK_INDEX,
                            CommonUtils.hexStringToBytes(factor)), PinManageType.FIXED,
                    AccountInputType.UNUSE_ACCOUNT, "", new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
                    14, new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
                    data);

            str = CommonUtils.bytesToHexString(pinInputResult.getPinblock());

        } catch (Exception e) {
            HPLog.e(TAG, "calc pin failed", e);
        }

        if (null != str) {
            str.toUpperCase(Locale.US);
        }
        return str;
    }

    public NewlandSwiperME15(Context context, String address, IShowSelectApplication selectApplication) {

        mDeviceManager = ConnUtils.getDeviceManager();
        mIsSwiperOK = true;
        this.mSelectApplication = selectApplication;
        try {
            initMe3xDeviceController(context, new BlueToothV100ConnParams(
                    address));
        } catch (Exception e) {
            HPLog.i(TAG, "", e);
            mIsSwiperOK = false;
        }

    }

    //获取设备电量
    public void getPowerLevel() {
        BatteryInfoResult powerLevel = mDeviceManager.getDevice().getBatteryInfo();
        Log.e("POWER", powerLevel.getElectricBattery() + "___电量");
        int power = Integer.parseInt(powerLevel.getElectricBattery());
        if (power < 90) {
            if (null != mSelectApplication
                    && mSelectApplication instanceof SwiperCallback) {
                ((SwiperCallback) mSelectApplication).onBatteryLow();
            }
        }
    }


    @Override
    public String getCSN() {
        if (connect()) {
            try {

                DeviceInfo deviceInfo = mDeviceManager.getDevice()
                        .getDeviceInfo();
                HPLog.i("getCSN", deviceInfo);
                String csn = deviceInfo.getCSN();

                if (null != deviceInfo && !ZZTConfig.ENV.SWIPERCSN) {
                    csn = ZZTConfig.ENV.CSN;
                }
                if (!TextUtils.isEmpty(csn)) {
                    csn = csn.replace("=", "D");
                }

                // update csn for test.
                // csn="E3B9FB104CDCF49E0100";
                HPLog.e("CSN", csn);

                return csn;
            } catch (ProcessTimeoutException processTimeoutException) {
                HPLog.e(TAG, "", processTimeoutException);
            } catch (Exception e) {
                HPLog.e(TAG, "", e);
            }
        }
        return null;
    }

    @Override
    public boolean stopOperation() {
        boolean result = false;
//        new AsyncTask<Void, Void, Void>() {
//            @Override
//            protected Void doInBackground(Void... params) {
//                HPLog.e(TAG, "stopOperation" + " doInBackground");
//                if (DeviceManager.DeviceConnState.CONNECTED == mDeviceManager
//                        .getDeviceConnState())
//                {
//                    HPLog.e(TAG, "stopOperation" + " doInBackground execute");
//                    try
//                    {
//                        Device device = mDeviceManager.getDevice();
//                        if (null != device) {
//                            CardReader cardReader =
//                                    (CardReader) device.getStandardModule(ModuleType.COMMON_CARDREADER);
//                            if (null != cardReader) {
//                                cardReader.cancelCardRead();
//                            }
//                            device.cancelCurrentExecute();
//                            device.reset();
//                        }
//                    }
//                    catch (Exception e)
//                    {
//                        HPLog.e(TAG, "撤消指令执行失败!", e);
//                    }
//
//                }
//                return null;
//            }
//        }.execute();
        if (DeviceManager.DeviceConnState.CONNECTED == mDeviceManager
                .getDeviceConnState()) {
            HPLog.e(TAG, "stopOperation" + " doInBackground execute");
            try {
                Device device = mDeviceManager.getDevice();
                if (null != device) {
                    CardReader cardReader =
                            (CardReader) device.getStandardModule(ModuleType.COMMON_CARDREADER);
                    if (null != cardReader) {
                        cardReader.cancelCardRead();
                    }
                    device.cancelCurrentExecute();
                    device.reset();
                }
            } catch (Exception e) {
                HPLog.e(TAG, "撤消指令执行失败!", e);
            }

        }
        return result;
    }

    @Override
    public boolean closeDevice() {
        mContext = null;
        mConnParams = null;
        mIsSwiperOK = false;
        if (mDeviceManager != null) {
            mDeviceManager.destroy();
            mDeviceManager = null;
        }
        return true;
    }

    private void clearScreen() {
        if (mDeviceManager == null) {
            return;
        }
        //避免程序崩溃
        Device d = mDeviceManager.getDevice();
        if (null == d) {
            return;
        }
        LCD lcd = (LCD) d.getStandardModule(
                ModuleType.COMMON_LCD);
        if (lcd != null) {
            lcd.clearScreen();
        }
    }

    private String mDynamicKey;

    @Override
    public SwipeResult swipeCard(String factor, int timeout) {
//        HPLog.i(TAG, "2014070707070780 : 0123456789abcdef");
//        String encMac = encData("0123456789abcdef",ISwiperListener.MacDataIndex , "2014070707070780");
//        HPLog.i(TAG, "mac: " + encMac);
//		getPowerLevel();
        SwipeResult swipeResult;
        mDynamicKey = CommonUtils.bytesToHexString(getDynamicKeyData());
        mHTData.clear();


        try {
            // 2015092517461080
            String strDate = factor.substring(0, 14);
            SimpleDateFormat df = new SimpleDateFormat("yyyyMMddhhmmss");
            Date date = null;
            try {
                date = df.parse(strDate);
            } catch (Exception e) {
                HPLog.i("setDeviceDate set date fail", date.toString());
            }

            mDeviceManager.getDevice().setDeviceDate(date);
            HPLog.i("setDeviceDate", date.toString());


//			String message;
            String swipe = mContext.getString(R.string.newland_swipe);
            // 如果，用户确认过金额，显示金额。没有直接显示请刷卡
            // 如果超级转账，金额也不是显示的。
            if (TextUtils.isEmpty(mAmount) || mFlag == SwiperMode.SUPER_TRANS) {
                message = swipe;
            } else {
                BigDecimal bd = new BigDecimal(mAmount);
                bd = bd.divide(new BigDecimal("100"));
                message = mContext.getString(R.string.newland_amount)
                        + bd.toString() + "\n" + swipe;
            }
            //clearScreen();
//			SwipResult result = swipCard(message, timeout, factor,
//					CommonUtils.hexStringToBytes(mDynamicKey));
            //Caojun 刷卡
            SwipResult result = null;
            try {
                BigDecimal amt = new BigDecimal(0);
                if (!TextUtils.isEmpty(mAmount)) {
                    amt = new BigDecimal(mAmount);
                }
                icTransferListener.setFactor(factor);
                result = startTransfer(new ModuleType[]{
                                ModuleType.COMMON_SWIPER,
                                ModuleType.COMMON_ICCARD},
                        message, amt, factor,
                        CommonUtils.hexStringToBytes(mDynamicKey), timeout,
                        TimeUnit.SECONDS,
                        icTransferListener);
            } catch (DeviceRTException e) {
                if (e.code == Integer.MIN_VALUE) {
                    if ("IC".equals(e.getMessage())) {
                        //IC卡
                        HPLog.e("icSwipeResult", "icSwipeResult");
                        if (null == icSwipeResult) {
                            return new SwipeResult(SwipeStatus.SWIPE_ERROR);
                        } else {
                            mHTData.put(IBusinessSwiper.BANK_DYNAMIC_KEY, mDynamicKey.toUpperCase(Locale.US));
                            return icSwipeResult;
                        }
                    }
                } else {
                    HPLog.e(TAG, "", e);
                    return new SwipeResult(SwipeStatus.SWIPE_ERROR);
                }
            } catch (Exception e) {
                HPLog.i(TAG, "", e);
                return new SwipeResult(SwipeStatus.SWIPE_ERROR);
            } finally {
                //clearScreen();
            }
            if (null == result) {
                return new SwipeResult(SwipeStatus.SWIPE_CANCEL);
            }
            //readTrack_timeout当做读卡超时
            if (SwipResultType.READTRACK_TIMEOUT == result.getRsltType()) {
                return new SwipeResult(SwipeStatus.SWIPE_TIMEOUT);
            }
            if (null == result.getSecondTrackData()) {
                return new SwipeResult(SwipeStatus.SWIPE_ERROR);
            }
            // 刷卡的时候，记录二磁道，dynamicKey, 还有卡号明文.
            // 其他的，譬如pin,卡号密文，金额密文等。输入密码后，做加密后加入。
            mHTData.put(IBusinessSwiper.BANK_TRACK2_KEY,
                    CommonUtils.bytesToHexString(result.getSecondTrackData())
                            .toUpperCase(Locale.US));
            mHTData.put(IBusinessSwiper.BANK_DYNAMIC_KEY, mDynamicKey.toUpperCase(Locale.US));
            mHTData.put(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY, result.getAccount().getAcctNo());
            // 保存hashKey，用于输入密码用
            mHTData.put(BANK_ACCOUNT_HASH_KEY, result.getAccount()
                    .getAcctHashId());
            //新版2.0.0 expiryDate
            String expireDate = result.getValidDate();
            if (CommonUtils.checkExpireDate(expireDate)) {
                expireDate = expireDate.substring(0, 4);
                HPLog.i(HPLog.FDL_TAG, "GjackSwiper  -- plainExpireDate:" + expireDate);
                mHTData.put(IBusinessSwiper.BANK_PLAIN_EXPIRE_DATE, expireDate);
            } else {
                HPLog.i(TAG, "GjackSwiper IC card but no plainExpireDate");
            }
            swipeResult = new SwipeResult(SwipeStatus.SWIPE_OK, result
                    .getAccount().getAcctNo());
            swipeResult.mCardType = result.getServiceCode().substring(0, 1);

        } catch (ProcessTimeoutException processTimeoutException) {
            HPLog.e(TAG, "", processTimeoutException);
            swipeResult = new SwipeResult(SwipeStatus.SWIPE_TIMEOUT);
        } catch (DeviceRTException e) {
            HPLog.e(TAG, "", e);
            swipeResult = new SwipeResult(SwipeStatus.SWIPE_ERROR);
        }
        return swipeResult;
    }

    private SwipResult swipCard(String msg, long timeout, String factor,
                                byte[] dynamicData) {
        CardReader cardReader = (CardReader) mDeviceManager.getDevice()
                .getStandardModule(ModuleType.COMMON_CARDREADER);
        if (cardReader == null) {
            throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
                    "not support read card!");
        }
        try {
            ModuleType[] openedModuleTypes = cardReader.openCardReader(msg,
                    new ModuleType[]{ModuleType.COMMON_SWIPER}, timeout,
                    TimeUnit.SECONDS);
            if (openedModuleTypes == null || openedModuleTypes.length <= 0) {
                HPLog.i(TAG,
                        "start card reader,but return is none!may user canceled?");
                return null;
            }
            if (openedModuleTypes.length > 1) {
                HPLog.i(TAG,
                        "should return only one type of card read action! but is "
                                + openedModuleTypes.length);
                throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
                        "should return only one type of card read action!but is "
                                + openedModuleTypes.length);
            }
            switch (openedModuleTypes[0]) {
                case COMMON_SWIPER:
                    Swiper swiper = (Swiper) mDeviceManager.getDevice()
                            .getStandardModule(ModuleType.COMMON_SWIPER);
                    SwipResult swipRslt = getSwipResult(
                            swiper,
                            MKIndexConst.DEFAULT_TRACK_WK_INDEX,
                            MESeriesConst.TrackEncryptAlgorithm.BY_HANDPAY_MODEL,
                            factor, dynamicData);
                    if (swipRslt.getRsltType() == SwipResultType.SUCCESS) {
                        return swipRslt;
                    }
                    throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
                            "swipe failed:" + swipRslt.getRsltType());
//				case COMMON_SWIPER_ERROR:
//					throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
//							"swip failed: COMMON_SWIPER_ERROR");
                default:
                    throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
                            "not support card reader module:"
                                    + openedModuleTypes[0]);

            }
        } finally {
            //
            // 梦想世界(61516903)  16:28:46
            // 不要调用 cardReader.closeCardReader(); 这个试试
            // cardReader.closeCardReader();
        }
    }


    private SwipResult getSwipResult(Swiper swiper, int trackKey,
                                     String encryptType, String factor, byte[] dynamicData) {
        SwipResult swipRslt = swiper.readSimposResult(new SwiperReadModel[]{
                        SwiperReadModel.READ_SECOND_TRACK,
                        SwiperReadModel.READ_THIRD_TRACK},
                TrackSecurityPaddingType.STANDARD_MODEL, new WorkingKey(
                        trackKey, CommonUtils.hexStringToBytes(factor)),
                encryptType, dynamicData, null);

        return swipRslt;

/*		connectDevice();
		appendInteractiveInfoAndShow("请刷卡或插卡...");
		
		SwipResult swipRslt = swipCardForME11("", 30000L, TimeUnit.MILLISECONDS);
		if (swipRslt == null) {
			btnStateInitFinished();
			return  null;
		}
		
		ModuleType[] moduleType = ((ME11SwipResult)swipRslt).getReadModuleType();
		if (moduleType[0] == ModuleType.COMMON_ICCARD) {
			mTime = System.currentTimeMillis();
			controller.startEmv(new BigDecimal("30.00"), new SimpleTransferListener());
		} else if (moduleType[0] == ModuleType.COMMON_SWIPER) {
			byte[] secondTrack = swipRslt.getSecondTrackData();
			byte[] thirdTrack = swipRslt.getThirdTrackData();
*/
    }

    /**
     * 获取随机数
     *
     * @param length
     * @return
     */
    public static byte[] getRandom(int length) {
        if (length < 1) {
            return null;
        }
        Random random = new Random();
        byte[] bytes = new byte[length];
        random.nextBytes(bytes);
        return bytes;
    }

    public static byte[] getDynamicKeyData() {
        try {
            byte[] rand = getRandom(8);
            // FIX RANDOM
            // rand = CommonUtils.hexStringToBytes("08745B3041F93398");
            return rand;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public String encData(String data, String index, String factor) {
        String result = null;

        if (ISwiperListener.MacDataIndex.equals(index)) {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            try {
                bos.write(String.valueOf(data.toCharArray()).getBytes());
                bos.write(0x80);
                while (bos.size() % 8 != 0) {
                    bos.write(0x00);
                }
                bos.write(0x80);
                for (int i = 0; i < 7; i++) {
                    bos.write(0x00);
                }
                byte[] macPlainBytes = bos.toByteArray();
                HPLog.i(TAG, "mac :" + CommonUtils.bytesToHexString(macPlainBytes));
                result = encMac(macPlainBytes, factor);
            } catch (IOException ioe) {
                HPLog.e(TAG, "", ioe);
                try {
                    bos.close();
                } catch (IOException e) {
                    HPLog.e(TAG, "", e);
                }
            }

        } else if (ISwiperListener.KeyDataIndex.equals(index)) {
            if (mFlag == SwiperMode.NORMAL_TRANS) {
                result = encData(data, factor);
            } else {
                data = contentToEncry(data, index);
                result = encData(data, factor);
            }


        } else if (PIN_INDEX.equals(index)) {
            //String.valueOf(data.toCharArray()).getBytes()

            // no description for parameter. try one.
            // CommonUtils.hexStringToBytes(data)
            result = encPin(data.getBytes(), factor);
        }

        // } else if (mFlag == SwiperMode.SUPER_TRANS) {
        // if (ISwiperListener.MacDataIndex.equals(index)) {
        // result = encMac(data.getBytes(), factor);
        // } else if (ISwiperListener.KeyDataIndex.equals(index)) {
        //
        // }
        // }
        return result;
    }

    @Override
    public Hashtable<String, String> batchEncData(
            Hashtable<Integer, String> htDatas, String factor) {
        return null;
    }

    private SwiperMode mFlag;

    @Override
    public boolean setMode(SwiperMode flag) {
        mFlag = flag;
        clearData();
        return true;
    }

    private void clearData() {
        mAmount = null;
    }

    private String mAmount = null;

    PinInputEvent event = null;

    /*
	@Override
	public Result inputPwd(final String factor, final int timeout)
	{
		if (!connect())
		{
			return Result.ERROR;
		}
		
//		String accHashId = mHTData.get(BANK_ACCOUNT_HASH_KEY);
//		String plainAcc = mHTData.get(BANK_PLAIN_ACCOUNT_KEY);
        String DCData = mHTData.get(IBusinessSwiper.BANK_DCDATA);
        
        // encrpted pin store in BANK_PAN_KEY
        String pin = mHTData.get(IBusinessSwiper.BANK_PAN_KEY);
        
//		// 前面貌似没有刷卡，报错！
//		if (TextUtils.isEmpty(DCData) && (TextUtils.isEmpty(accHashId) || TextUtils.isEmpty(plainAcc)))
//		{
//			HPLog.e(TAG, "no card relative info.");
//			return Result.ERROR;
//		}
		
		final String msg;
		// 有输入金额：转账
		// 无输入金额：余额查询
		String inputPwd = mContext.getString(R.string.newland_input_pwd);
		if (!TextUtils.isEmpty(mAmount))
		{
			BigDecimal bd = new BigDecimal(mAmount);
			bd = bd.divide(new BigDecimal("100"));
			msg = mContext.getString(R.string.newland_amount) + bd.toString()
					+ "\n" + inputPwd;
		}
		else
		{
			msg = inputPwd;
		}
//		PinInputEvent event = null;
        //如果没有获取到银行卡密码，进入银行卡密码输入界面
        if (TextUtils.isEmpty(pin)) {
            clearScreen();
            try {
                final PinInput pinInput = (PinInput) mDeviceManager.getDevice()
                        .getStandardModule(ModuleType.COMMON_PININPUT);
                //IC卡输入密码
                if (!TextUtils.isEmpty(DCData)) {
                    try {
                        event = startPininput(AccountInputType.UNUSE_ACCOUNT,
                                CommonUtils.str2Bcd(factor), "00000000000000000000", 6,
                                true, msg, timeout);
                    } catch (InterruptedException e) {
                        HPLog.e("startPininput", e.toString());
                    }
                }
                //磁条卡输入密码
                else {
                    event = pinInput.startStandardPinInput(
                            new WorkingKey(MKIndexConst.DEFAULT_PIN_WK_INDEX,
                                    CommonUtils.hexStringToBytes(factor)),
                            PinManageType.FIXED, AccountInputType.UNUSE_ACCOUNT,
                            "00000000000000000000", 6, new byte[]{'F', 'F', 'F', 'F', 'F', 'F',
                                    'F', 'F', 'F', 'F'}, true, msg, timeout,
                            TimeUnit.SECONDS);
                }

                clearScreen();
                // FIXME 如何处理超时问题的？
                if (event == null) {
                    return Result.CANCEL;
                }
            } catch (ProcessTimeoutException processTimeoutException) {
                return Result.TIMEOUT;
            }
            pin = CommonUtils.bytesToHexString(event.getEncrypPin());
            if ("0000000000000000".equals(pin)) {
                pin = null;
            }
        }
        

        return Result.OK;

/*        // 加密卡号。加密账号，需要先转化为hex。
		String encAcc = null;
		if (mFlag == SwiperMode.NORMAL_TRANS)
		{
			encAcc = encData(CommonUtils.string2Hex(plainAcc),
					ISwiperListener.KeyDataIndex, factor);
		}
		else if (mFlag == SwiperMode.SUPER_TRANS)
		{
			encAcc = encData(plainAcc, ISwiperListener.KeyDataIndex, factor);
		}
		if (!TextUtils.isEmpty(pin) && !TextUtils.isEmpty(encAcc))
		{
			mHTData.put(BANK_PAN_KEY, pin.toUpperCase(Locale.US));
			mHTData.put(BANK_ACCOUNT_KEY, encAcc);
			if (!TextUtils.isEmpty(mAmount))
			{
				// 加密金额
				String encAmt = encData(mAmount, ISwiperListener.KeyDataIndex,
						factor);
				if (!TextUtils.isEmpty(encAmt))
				{
					mHTData.put(BANK_AMOUNT_KEY, encAmt);
					return Result.OK;
				}
				HPLog.i(TAG, "enc amount error!");
				return Result.ERROR;
			}
			else
			{
				return Result.OK;
			}
		}
		else
		{
			HPLog.e(TAG, "encData error!");
			return Result.ERROR;
		}

        }
        */
    @SuppressWarnings("unchecked")
    @Override
    public Hashtable<String, String> getBankInfo() {
        Hashtable<String, String> result = (Hashtable<String, String>) mHTData
                .clone();
        mHTData.clear();
        return result;
    }

    @Override
    public boolean isSwiperReady() {
        return mIsSwiperOK;
    }

    @Override
    public SwiperModel getSwiperModel() {
        return SwiperModel.ME15_BLUETOOTH;
    }


    /**
     * 事件线程阻塞控制监听器.
     *
     * @param <T>
     * @author lance
     */
    private class EventHolder<T extends DeviceEvent> implements
            DeviceEventListener<T> {
        private T event;
        private final Object syncObj = new Object();
        private boolean isClosed = false;

        public void onEvent(T event, Handler handler) {
            this.event = event;
            synchronized (syncObj) {
                isClosed = true;
                syncObj.notify();
            }
        }

        public Handler getUIHandler() {
            return null;
        }

        void startWait() throws InterruptedException {
            synchronized (syncObj) {
                if (!isClosed)
                    syncObj.wait();
            }
        }
    }

    public class AppExCode {

        public static final int DRIVER_NOT_FOUND = 1000;

        public static final int INIT_DRIVER_FAIED = 1001;

        public static final int INIT_DEVICE_PARAMS_FAILED = 1002;

        public static final int GET_TRACKTEXT_FAILED = 1003;

        public static final int GET_PININPUT_FAILED = 1004;

        public static final int GET_KEYBOARD_VALUE_FAILED = 1005;

        public static final int GET_PLAIN_ACCOUNT_NO_FAILED = 1006;

        public static final int MK_INDEX_NOTFOUND_ERROR = 1007;

        public static final int LOAD_WORKINGKEY_FAILED = 1009;
    }

    /**
     * 主密钥索引
     * <p/>
     * <p/>
     * 各索引若相同则表示使用同一组主密钥索引
     *
     * @author lance
     */
    public static class MKIndexConst {

        /**
         * 主密钥索引
         */
        public static final int DEFAULT_MK_INDEX = 1;
        /**
         * 默认PIN加密工作密钥索引
         */
        public static final int DEFAULT_PIN_WK_INDEX = 2;
        /**
         * 默认MAC加密工作密钥索引
         */
        public static final int DEFAULT_MAC_WK_INDEX = 3;
        /**
         * 默认磁道加密工作密钥索引
         */
        public static final int DEFAULT_TRACK_WK_INDEX = 4;

        public static final int DEFAULT_MUTUALAUTH_WK_INDEX = 5;
    }

    /**
     * 超级转账模式下模式下，数据的处理
     *
     * @param data
     * @param keyIndex
     * @return
     */
    private String contentToEncry(String data, String keyIndex) {
        data = StringToA(data);
        // 只有做mac的时候，需要补80
        if (ISwiperListener.MacDataIndex.equals(keyIndex)) {
            data = data + "80";
        }
        StringBuilder builder;
        if (data.length() % 16 != 0) {
            builder = new StringBuilder();
            builder.append(data);
            while (builder.toString().length() % 16 != 0) {
                builder.append("0");
            }
            data = builder.toString();
        }
        return data;
    }

    /**
     * 将string转化为ascii
     */
    private String StringToA(String content) {
        String result = "";
        int max = content.length();
        for (int i = 0; i < max; i++) {
            char c = content.charAt(i);
            String ss = Integer.toHexString((int) c);
            result = result + ss;
        }
        return result;
    }

    private String packageByte(String str) {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            bos.write(str.getBytes().length);
            bos.write(str.getBytes());
            if (bos.size() % 8 != 0) {
                bos.write(0x80);
            }
            while (bos.size() % 8 != 0) {
                bos.write(0x00);
            }
            return new String(bos.toByteArray());
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        return null;
    }

    ////////////////////////////////////////////////////////
    //IC卡
    private ICTransferListener icTransferListener = new ICTransferListener();

    private void isConnected() {
        synchronized (ME15_DRIVER_NAME) {
            if (null == mDeviceManager || mDeviceManager.getDevice() == null) {
                throw new DeviceOutofLineException("device not connect!");
            }
        }
    }

    private <T extends AbstractProcessDeviceEvent> T preEvent(T event,
                                                              int defaultExCode) {
        if (!event.isSuccess()) {
            if (event.isUserCanceled()) {
                return null;
            }
            if (event.getException() != null) {
                if (event.getException() instanceof RuntimeException) {// 运行时异常直接抛出.
                    throw (RuntimeException) event.getException();
                }
                throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
                        "open card reader meet error!", event.getException());
            }
            throw new DeviceRTException(ExCode.UNKNOWN,
                    "unknown exception!defaultExCode:" + defaultExCode);
        }
        return event;
    }

    /**
     * @param cardReaders
     * @param msg
     * @param amt
     * @param factor
     * @param dynamicKeyData
     * @param timeout
     * @param timeunit
     * @param transferListener
     * @return null 表示取消
     */
    private SwipResult startTransfer(ModuleType[] cardReaders, String msg,
                                     BigDecimal amt, String factor, byte[] dynamicKeyData, long timeout, TimeUnit timeunit,
                                     TransferListener transferListener) {

        isConnected();
        CardReader cardReader = (CardReader) mDeviceManager.getDevice()
                .getStandardModule(ModuleType.COMMON_CARDREADER);
        if (cardReader == null) {
            throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
                    "not support read card!");
        }
        try {
            EventHolder<OpenCardReaderEvent> listener = new EventHolder<OpenCardReaderEvent>();
            cardReader.openCardReader(msg, cardReaders, timeout, timeunit, listener);
            try {
                listener.startWait();
            } catch (InterruptedException e) {
                cardReader.cancelCardRead();
                return new SwipResult(SwipResultType.READTRACK_TIMEOUT);
            } finally {
                clearScreen();
            }
            OpenCardReaderEvent event = listener.event;
            //event.getException()
            if (!event.isSuccess()) {
                if (event.isUserCanceled()) {
                    return null;
                } else if (null != event.getException() && event.getException() instanceof ProcessTimeoutException) {
                    return new SwipResult(SwipResultType.READTRACK_TIMEOUT);
                } else if (event.isFailed() || null != event.getException()) {
                    return new SwipResult(SwipResultType.SWIP_FAILED);
                }
                //TODO 暂时失败处理
                return new SwipResult(SwipResultType.SWIP_FAILED);
            }
            ModuleType[] openedModuleTypes = event.getOpenedCardReaders();
            if (openedModuleTypes == null || openedModuleTypes.length <= 0) {
                HPLog.e("startTransfer", "start cardreader,but return is none!may user canceled?");
                return null;
            }
            if (openedModuleTypes.length > 1) {
                HPLog.w("startTransfer", "should return only one type of cardread action!but is "
                        + openedModuleTypes.length);
                throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
                        "should return only one type of cardread action!but is "
                                + openedModuleTypes.length);
            }
            Date curDate = new Date(System.currentTimeMillis());//获取当前时间
            mDeviceManager.getDevice().setDeviceDate(curDate);
            switch (openedModuleTypes[0]) {

                case COMMON_SWIPER:
                    int trackKey = MKIndexConst.DEFAULT_TRACK_WK_INDEX;
                    Swiper swiper = (Swiper) mDeviceManager.getDevice()
                            .getStandardModule(ModuleType.COMMON_SWIPER);
                    SwipResult swipRslt = getSwipResult(swiper, trackKey,
                            TrackEncryptAlgorithm.BY_HANDPAY_MODEL, factor, dynamicKeyData);
                    HPLog.e("swipRslt.getRsltType()", swipRslt.getRsltType().name());
                    HPLog.e("SwipResultType.SUCCESS", SwipResultType.SUCCESS.name());
                    if (swipRslt.getRsltType() == SwipResultType.SUCCESS) {
                        return swipRslt;
                    }
                    //TODO 刷卡失败
                    return new SwipResult(SwipResultType.SWIP_FAILED);
                case COMMON_ICCARD:

//					OnlinePinConfig config = new OnlinePinConfig();
//					config.setWorkingKey(new WorkingKey(
//							MKIndexConst.DEFAULT_PIN_WK_INDEX, CommonUtils.hexStringToBytes(factor)));
//					config.setPinManageType(PinManageType.FIXED);
//					config.setPinPadding(new byte[] { 'F', 'F', 'F', 'F', 'F',
//							'F', 'F', 'F', 'F', 'F' });
//					config.setDisplayContent("请输入密码:");
//					config.setTimeout((int)timeout);
//					config.setInputMaxLen(6);
//					config.setEnterEnabled(true);
//					module.setOnlinePinConfig(config);
//                    EmvTransController controller = module
//                            .getEmvTransController(transferListener);
//                    controller.startEmv(amt, new BigDecimal("0"), true);
                    EmvModule module;
                    if (mDeviceManager.getDevice().getDeviceInfo().getPID() == DeviceType.ME15B) {
                        module = (EmvModule) mDeviceManager.getDevice().getExModule("EMV_LEVEL2");
                    } else {
                        module = (EmvModule) mDeviceManager.getDevice().getStandardModule(ModuleType.COMMON_EMV);
                    }
                    isConnected();
                    module.initEmvModule(mContext);
                    module.setOnlinePinConfig(null);
                    EmvTransController controller = module
                            .getEmvTransController(transferListener);
                    controller.startEmv(0, 1, new BigDecimal("0"), true);
                    icSwipeResult = null;
                    lock();
                    throw new DeviceRTException(Integer.MIN_VALUE, "IC");
                default: {
                    throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
                            "not support cardreader module:"
                                    + openedModuleTypes[0]);
                }
            }
        } finally {
            cardReader.closeCardReader();
        }
    }

    private void doICTransfer(final EmvTransInfo context, String factor) {

        try {
            //mDynamicKey = CommonUtils.bytesToHexString(getDynamicKeyData());

            // 1.拼DCData
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            HPLog.e("82", ISOUtils.hexString(context
                    .getApplicationInterchangeProfile()));
            byte[] bytes82 = context
                    .getApplicationInterchangeProfile();
            if (bytes82 != null) {
                bos.write((byte) 0x82);
                bos.write(bytes82.length);
                bos.write(bytes82);
            }
            HPLog.e("9F36", ISOUtils.hexString(context
                    .getAppTransactionCounter()));
            byte[] bytes9F36 = context.getAppTransactionCounter();
            if (bytes9F36 != null) {
                bos.write((byte) 0x9F);
                bos.write((byte) 0x36);
                bos.write(bytes9F36.length);
                bos.write(bytes9F36);
            }
            HPLog.e("9F26",
                    ISOUtils.hexString(context.getAppCryptogram()));
            byte[] bytes9F26 = context.getAppCryptogram();
            if (bytes9F26 != null) {
                bos.write((byte) 0x9F);
                bos.write((byte) 0x26);
                bos.write(bytes9F26.length);
                bos.write(bytes9F26);
            }
            HPLog.e("9F27", CommonUtils
                    .bytesToHexString(new byte[]{context
                            .getCryptogramInformationData()}));
            byte[] bytes9F27 = new byte[]{context
                    .getCryptogramInformationData()};
            if (bytes9F27 != null) {
                bos.write((byte) 0x9F);
                bos.write((byte) 0x27);
                bos.write(bytes9F27.length);
                bos.write(bytes9F27);
            }
            HPLog.e("9F33", ISOUtils.hexString(context
                    .getTerminal_capabilities()));
            byte[] bytes9F33 = context.getTerminal_capabilities();
            if (bytes9F33 != null) {
                bos.write((byte) 0x9F);
                bos.write((byte) 0x33);
                bos.write(bytes9F33.length);
                bos.write(bytes9F33);
            }
            HPLog.e("95", ISOUtils.hexString(context
                    .getTerminalVerificationResults()));
            byte[] bytes95 = context
                    .getTerminalVerificationResults();
            if (bytes95 != null) {
                bos.write((byte) 0x95);
                bos.write(bytes95.length);
                bos.write(bytes95);
            }
            HPLog.e("9F37", ISOUtils.hexString(context
                    .getUnpredictableNumber()));
            byte[] bytes9F37 = context.getUnpredictableNumber();
            if (bytes9F37 != null) {
                bos.write((byte) 0x9F);
                bos.write((byte) 0x37);
                bos.write(bytes9F37.length);
                bos.write(bytes9F37);
            }
            HPLog.e("9F02", context.getAmountAuthorisedNumeric());
            String str9F02 = CommonUtils.formatMoneyToPos(context
                    .getAmountAuthorisedNumeric(), 12);
            byte[] bytes9F02 = CommonUtils.str2Bcd(str9F02);
            if (bytes9F02 != null) {
                bos.write((byte) 0x9F);
                bos.write((byte) 0x02);
                bos.write(bytes9F02.length);
                bos.write(bytes9F02);
            }
            HPLog.e("9F03", context.getAmountOtherNumeric());
            String str9F03 = CommonUtils.formatMoneyToPos(context
                    .getAmountOtherNumeric(), 12);
            byte[] bytes9F03 = CommonUtils.str2Bcd(str9F03);
            if (bytes9F03 != null) {
                bos.write((byte) 0x9F);
                bos.write((byte) 0x03);
                bos.write(bytes9F03.length);
                bos.write(bytes9F03);
            }
            HPLog.e("9F1A", context.getTerminalCountryCode());
            String str9F1A = context.getTerminalCountryCode();
            byte[] bytes9F1A = CommonUtils.str2Bcd(str9F1A);
            if (bytes9F1A != null) {
                bos.write((byte) 0x9F);
                bos.write((byte) 0x1A);
                bos.write(bytes9F1A.length);
                bos.write(bytes9F1A);
            }
            HPLog.e("5F2A", context.getTransactionCurrencyCode());
            String str5F2A = context.getTransactionCurrencyCode();
            byte[] bytes5F2A = CommonUtils.str2Bcd(str5F2A);
            if (bytes5F2A != null) {
                bos.write((byte) 0x5F);
                bos.write((byte) 0x2A);
                bos.write(bytes5F2A.length);
                bos.write(bytes5F2A);
            }
            HPLog.e("9A", context.getTransactionDate());
            String str9A = context.getTransactionDate();
            byte[] bytes9A = CommonUtils.str2Bcd(str9A);
            if (bytes9A != null) {
                bos.write((byte) 0x9A);
                bos.write(bytes9A.length);
                bos.write(bytes9A);
            }
            HPLog.e("9C", CommonUtils
                    .bytesToHexString(new byte[]{context
                            .getTransactionType().byteValue()}));
            byte[] bytes9C = new byte[]{context
                    .getTransactionType().byteValue()};
            if (bytes9C != null) {
                bos.write((byte) 0x9C);
                bos.write(bytes9C.length);
                bos.write(bytes9C);
            }
            HPLog.e("9F10", ISOUtils.hexString(context
                    .getIssuerApplicationData()));
            byte[] bytes9F10 = context.getIssuerApplicationData();
            if (bytes9F10 != null) {
                bos.write((byte) 0x9F);
                bos.write((byte) 0x10);
                bos.write(bytes9F10.length);
                bos.write(bytes9F10);
            }
            byte[] dcDatas = bos.toByteArray();
            bos.close();
            String dcdata = CommonUtils
                    .bytesToHexString(dcDatas);
            String icnumber = context.getCardSequenceNumber();
            if (!TextUtils.isEmpty(icnumber)) {
                while (icnumber.length() < 3) {
                    icnumber = "0" + icnumber;
                }
                mHTData.put(IBusinessSwiper.BANK_ICNUMBER, icnumber);
            }
            String account = context.getCardNo();
            byte[] encPin = context.getOnLinePin();

            String PAN = context.getCardNo();
			
			/*			
			 * String track2=CommonUtils.bytesToHexString(context.getTrack_2_eqv_data());
			mHTData.put(IBusinessSwiper.BANK_TRACK2_KEY, track2.toUpperCase(Locale.US));
			 */

//			梦想世界(61516903)  10:05:05
//			直接在onRequestOnline回调里头 调用context.getTrack_2_eqv_data()就是密文数据了

            Log.e("ME15", factor + "-----" + mDynamicKey);
            SwipResult swipResult = getTrackText(factor, ISOUtils.hex2byte(mDynamicKey));
            if (null != swipResult.getSecondTrackData()) {
                String track2 = CommonUtils.bytesToHexString(swipResult.getSecondTrackData());

                mHTData.put(IBusinessSwiper.BANK_TRACK2_KEY, track2.toUpperCase(Locale.US));
            }


            mHTData.put(IBusinessSwiper.BANK_DCDATA, dcdata.toUpperCase(Locale.US));
            mHTData.put(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY, account);
            //新版2.0.0 expiryDate
            String expireDate = context.getCardExpirationDate();

            if (CommonUtils.checkExpireDate(expireDate)) {
                expireDate = expireDate.substring(0, 4);
                HPLog.i(HPLog.FDL_TAG, "GjackSwiper  -- plainExpireDate:" + expireDate);
                mHTData.put(IBusinessSwiper.BANK_PLAIN_EXPIRE_DATE, expireDate);
            } else {
                HPLog.i(TAG, "GjackSwiper IC card but no plainExpireDate");
            }
            boolean isNeedPwd = true;
            //用户直接输入确认，下面会返回8个字节的全零。我们需要把他当每输入密码
            if (encPin != null && "0000000000000000".equals(CommonUtils.bytesToHexString(encPin))) {
                encPin = null;
            }
            if (encPin != null) {
                mHTData.put(IBusinessSwiper.BANK_PAN_KEY, CommonUtils.bytesToHexString(encPin));
                isNeedPwd = false;
            }
            icSwipeResult = new SwipeResult(SwipeStatus.SWIPE_OK, account, isNeedPwd);
        } catch (IOException e) {
            HPLog.e("doICTransfer", e.toString());
        }
    }

    public SwipResult getTrackText(String factor, byte[] dynamicKeyData) {
        Swiper swiper = (Swiper) mDeviceManager.getDevice().getStandardModule(ModuleType.COMMON_SWIPER);
        Log.e("ME15", dynamicKeyData + "---" + factor);
       /* SwipResult swipRslt = swiper.readEncryptResult(new SwiperReadModel[] { SwiperReadModel.READ_IC_SECOND_TRACK},
                new WorkingKey(MKIndexConst.DEFAULT_TRACK_WK_INDEX,CommonUtils.hexStringToBytes(factor)),
                TrackEncryptAlgorithm.BY_HANDPAY_MODEL, dynamicKeyData, null);*/

        SwipResult swipRslt = swiper.readSimposResult(new SwiperReadModel[]{
                        SwiperReadModel.READ_IC_SECOND_TRACK},
                TrackSecurityPaddingType.STANDARD_MODEL, new WorkingKey(
                        MKIndexConst.DEFAULT_TRACK_WK_INDEX, CommonUtils.hexStringToBytes(factor)),
                TrackEncryptAlgorithm.BY_HANDPAY_MODEL, dynamicKeyData, null);

        if (swipRslt.getRsltType() == SwipResultType.SUCCESS) {
            return swipRslt;
        }
        throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED, "swip failed:" + swipRslt.getRsltType());
    }

    private interface TransferListener extends EmvControllerListener {

        void onOpenCardreaderCanceled();
    }

    private class ICTransferListener implements TransferListener {
        private String mFactor;

        public void setFactor(String factor) {
            mFactor = factor;
        }

        @Override
        public void onEmvFinished(boolean arg0, EmvTransInfo context)
                throws Exception {
            //doICTransfer(context);
            //在插入IC卡，输入密码的时候，拔掉刷卡器，会直接进入这个回调。所以我们需要unlock。
            unlock();
            HPLog.i("NewlandSwiperBT", "onEmvFinished");
        }

        @Override
        public void onError(EmvTransController arg0, Exception arg1) {
            HPLog.i("NewlandSwiper", "onError", arg1);
            unlock();
            arg0.cancelEmv();
        }

        @Override
        public void onFallback(EmvTransInfo arg0) throws Exception {
            //应该降级交易，我们就当失败了。
            HPLog.i("NewlandSwiperBT", "onFallback");
            unlock();
        }

        @Override
        public void onRequestOnline(EmvTransController controller, EmvTransInfo context)
                throws Exception {
            HPLog.i("NewlandSwiper", "onRequestOnline");
            doICTransfer(context, mFactor);
            unlock();
        }

        @Override
        public void onRequestPinEntry(EmvTransController arg0, EmvTransInfo arg1)
                throws Exception {
            HPLog.i("NewlandSwiper", "onRequestPinEntry");
            //unlock();
            arg0.cancelEmv();
        }

        @Override
        public void onRequestSelectApplication(EmvTransController arg0,
                                               EmvTransInfo arg1) throws Exception {
            HPLog.i("NewlandSwiperBT", "onRequestSelectApplication");
            unlock();
            arg0.cancelEmv();
        }

        @Override
        public void onRequestTransferConfirm(EmvTransController arg0,
                                             EmvTransInfo arg1) throws Exception {
            HPLog.i("NewlandSwiper15", "onRequestTransferConfirm");
            unlock();
            arg0.cancelEmv();
        }

        @Override
        public void onOpenCardreaderCanceled() {
            unlock();
        }

    }

//	/**
//	 * 磁条卡交易
//	 */
//	private SwipResult startSwipTransfer(final SwipResult sr, final String message, final String amt, final long timeout, final TimeUnit timeUnit, final String factor)
//	{
//		CardReader cardReader = (CardReader) mDeviceManager.getDevice()
//				.getStandardModule(ModuleType.COMMON_CARDREADER);
//		if (cardReader == null)
//		{
//			throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
//					"not support read card!");
//		}
//		try
//		{
//			EventHolder<OpenCardReaderEvent> listener = new EventHolder<OpenCardReaderEvent>();
//			cardReader.openCardReader(message,
//					new ModuleType[] { ModuleType.COMMON_SWIPER }, timeout,
//					timeUnit, listener);
//			try
//			{
//				listener.startWait();
//			}
//			catch (InterruptedException e)
//			{
//				cardReader.cancelCardRead();
//				transferListener.onOpenCardreaderCanceled();
//			}
//			finally
//			{
//				clearScreen();
//			}
//			OpenCardReaderEvent event = listener.event;
//			event = preEvent(event, AppExCode.GET_TRACKTEXT_FAILED);
//			if (event == null)
//			{
//				return null;
//			}
//			ModuleType[] openedModuleTypes = event.getOpenedCardReaders();
//			if (openedModuleTypes == null || openedModuleTypes.length <= 0)
//			{
//				HPLog.e("startSwipTransfer","start cardreader,but return is none!may user canceled?");
//				return null;
//			}
//			if (openedModuleTypes.length > 1)
//			{
//				HPLog.e("startSwipTransfer","should return only one type of cardread action!but is "
//						+ openedModuleTypes.length);
//				throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
//						"should return only one type of cardread action!but is "
//								+ openedModuleTypes.length);
//			}
//			switch (openedModuleTypes[0])
//			{
//				case COMMON_SWIPER:
//					int trackKey = MKIndexConst.DEFAULT_TRACK_WK_INDEX;
//					Swiper swiper = (Swiper) mDeviceManager.getDevice()
//							.getStandardModule(ModuleType.COMMON_SWIPER);
//					SwipResult swipRslt = getSwipResult(swiper, trackKey,
//							TrackEncryptAlgorithm.BY_HANDPAY_MODEL, factor, CommonUtils.hexStringToBytes(mDynamicKey));
//					if (swipRslt.getRsltType() == SwipResultType.SUCCESS)
//					{
//						return swipRslt;
//					}
//					throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
//							"swip failed:" + swipRslt.getRsltType());
//				default:
//				{
//					throw new DeviceRTException(AppExCode.GET_TRACKTEXT_FAILED,
//							"not support cardreader module:"
//									+ openedModuleTypes[0]);
//				}
//			}
//		}
//		finally
//		{
//			cardReader.closeCardReader();
//		}
//	}

    public PinInputEvent startPininput(AccountInputType acctInputType,
                                       byte[] processKey, String acctHash, int inputMaxLen,
                                       boolean isEnterEnabled, String msg, long timeout)
            throws InterruptedException {
        isConnected();
        PinInput pinInput = (PinInput) mDeviceManager.getDevice().getStandardModule(ModuleType.COMMON_PININPUT);
        EventHolder<PinInputEvent> listener = new EventHolder<PinInputEvent>();
        pinInput.startStandardPinInput(new WorkingKey(MKIndexConst.DEFAULT_PIN_WK_INDEX, processKey), PinManageType.FIXED, acctInputType, acctHash, inputMaxLen, new byte[]{'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F'}, isEnterEnabled, msg, (int) timeout, TimeUnit.SECONDS, listener);
        try {
            listener.startWait();
        } catch (InterruptedException e) {
            pinInput.cancelPinInput();
            throw e;
        } finally {
            //clearScreen();
        }
        PinInputEvent event = listener.event;
        event = preEvent(event, AppExCode.GET_PININPUT_FAILED);
        if (event == null) {
            return null;
        }
        return event;
    }

    private String message;

    private SwipeResult icSwipeResult;
    private static Object objLockBT = new Object();
    private static boolean isSignalled = false;

    public static void lock() {
        synchronized (objLockBT) {
            while (!isSignalled) {
                try {
                    HPLog.e("lock", "lock");
                    objLockBT.wait();
                } catch (InterruptedException e) {
                    HPLog.e("unlock", e.toString());
                }
            }
            isSignalled = false;
        }
    }

    public static void unlock() {
        synchronized (objLockBT) {
            HPLog.e("unlock", "unlock");
            isSignalled = true;
            objLockBT.notify();
        }
    }


}
